package sfin.service;

import static org.apache.commons.lang.StringUtils.isBlank;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;

import sfin.swt.exception.StatizoException;
import sfin.swt.util.FormatterUtil;
import br.com.statizo.financeiro.core.repository.impl.ContaRepository;
import br.com.statizo.financeiro.domain.entity.impl.Banco;
import br.com.statizo.financeiro.domain.entity.impl.ContaCorrente;

public class ContaService  extends AbstractService implements ListService{

	private List<ContaCorrente> contas;
	
	private ContaCorrente applicationAccount;
	
	private BancoService bancoService;
	private ContaRepository contaRepository;
	
	public ContaService(ResourceBundle bundle, FormatterUtil formatterUtil, ContaRepository contaRepository) {
		super(bundle,formatterUtil);
		this.contaRepository = contaRepository;
		refresh();
		putDefault();
	}
	
	private void refresh(){
		contas = contaRepository.getList();
		sort();
	}
	
	private void putDefault(){
		ContaCorrente conta = contaRepository.getDefault();
		if(conta != null)
			applicationAccount = conta;
	}
	
	public int save(int index,String apelido, String agencia, String conta, int banco, boolean padrao) throws StatizoException{
		
		List<String> errors = new ArrayList<String>();
		
		if(isBlank(apelido)){
			errors.add(bundle.getString("current.account.edit.validation.required.name"));
		}
		
		if(isBlank(agencia)){
			errors.add(bundle.getString("current.account.edit.validation.required.agency"));
		}

		if(isBlank(conta)){
			errors.add(bundle.getString("current.account.edit.validation.required.number"));
		}

		if(banco < 0){
			errors.add(bundle.getString("current.account.edit.validation.required.bank"));			
		}
		
		Banco bc = null;
		try{
			 bc = bancoService.merge(bancoService.getAt(banco));
		}catch(Exception e){
			errors.add(e.getMessage());
		}
		
		if(errors.isEmpty()){
			ContaCorrente persistentConta = index >= 0 ? contas.get(index) : new ContaCorrente(); 
			persistentConta.setApelido(apelido);
			persistentConta.setAgencia(agencia);
			persistentConta.setNumero(conta);
			persistentConta.setBanco(bc);
			persistentConta.setPadrao(padrao);
			
			try{
				contaRepository.entityManagerRefresh();
				contaRepository.beginTransaction();
				
				if(padrao)
					contaRepository.cleanPadrao();
				
				persistentConta = contaRepository.merge(persistentConta);
				
				if(!contas.contains(persistentConta)){
					contas.add(persistentConta);
				}
				contaRepository.commit();
				refresh();
				notifyListeners();
				return contas.indexOf(persistentConta);
			}catch(Exception e){
				errors.add(e.getMessage());
				throw new StatizoException(errors);
			}
		}else{
			throw new StatizoException(errors);
		}
	}
	
	
	public String[][] getAll(){
		String[][] all = new String[contas.size()][5];
		for(int i = 0; i<contas.size(); i++){
			ContaCorrente conta = contas.get(i);
			all[i][0] = conta.getApelido();
			
			try{
				all[i][1] = conta.getBanco().getNome();	
			}catch(Exception e){}
			
			all[i][2] = conta.getAgencia();
			all[i][3] = conta.getNumero();
			all[i][4] = conta.isPadrao() ? "X" : "";				
		}
		return all;
	}
	
	
	public String[] getNomes(){
		String[] nomes = new String[contas.size()];
		for (int i = 0; i < contas.size(); i++) {
			nomes[i] = contas.get(i).getApelido();
		}
		return nomes;
	}
	
	public void sort(){
		Comparator<ContaCorrente> comparator = (c1,c2) -> c1.getApelido().compareTo(c2.getApelido());
		contas.sort(comparator);
	}
	
	public ContaCorrente getAt(int index){
		return contas.get(index);
	}
	
	public int indexOf(ContaCorrente conta){
		return contas.indexOf(conta);
	}

	public void setBancoService(BancoService bancoService) {
		this.bancoService = bancoService;
	}
	
	@Override
	public int size(){
		return this.contas.size();
	}

	public void delete(int selectedIndex) throws StatizoException {
		List<String> errors = new ArrayList<String>();
		try{
			ContaCorrente conta = contas.get(selectedIndex);
			
			contaRepository.entityManagerRefresh();
			contaRepository.beginTransaction();
			conta = contaRepository.merge(conta);
			contaRepository.remove(conta);
			contaRepository.commit();
			
			contas.remove(conta);	
			notifyListeners();
		}catch(Exception e){
			errors.add(bundle.getString("string.general.fixme"));
			throw new StatizoException(errors);
		}
	}

	public int getCurrentApplicationAccountIndex(){
		if(applicationAccount == null)
			return -1;
		return contas.indexOf(applicationAccount);
	}
	
	public void setApplicationAccountIndex(int index){
		if(index >= 0){
			applicationAccount = contas.get(index);
		}else{
			applicationAccount = null;
		}
		notifyListeners();	
	}
	
	public Serializable getApplicationAccountId(){
		if(applicationAccount == null)
			return null;
		return applicationAccount.getId();
	}
	
	public String getApplicationAccountName(){
		if(applicationAccount == null){
			return bundle.getString("application.toolbar.filter.currentAccount.all");
		}
		return applicationAccount.getApelido();
	}
	
	public ContaCorrente getCurrentAccount(){
		if(applicationAccount == null)
			return null;
		applicationAccount = contaRepository.merge(applicationAccount);
		contas.set(contas.indexOf(applicationAccount), applicationAccount);
		return applicationAccount;
	}
	
	@Override
	protected void notifyListeners() {

		super.notifyListeners();
	}
	
}